using System;
using System.Collections.Generic;
using System.Text;

using Mud.Common.Physical;
using System.Windows.Controls;
using System.Windows.Media.Media3D;

namespace Mud.Client.WPF.Graphics
{
    public class CreatureModel : Model
    {

        private TranslateTransform3D _translateTransform;
        private RotateTransform3D _rotateTransform;
        private ScaleTransform3D _scaleTransform;

        public Creature Creature
        {
            get { return _creature; }
        }
        private Creature _creature;


        public CreatureModel(Viewport3D viewport3D, Creature creature)
            : base(viewport3D)
        {
            _creature = creature;
            this.ModelVisual3D = new ModelVisual3D();
            this.ModelVisual3D.Content = Ab3d.Reader3ds.Read("Data\\Meshes\\Character.3DS");
        }

        public override void AddToScene()
        {
            _creature.GameObjectChanged += CreatureChanged;
 
            Transform3DGroup group = new Transform3DGroup();
            _translateTransform = new TranslateTransform3D(_creature.Location.X, _creature.Location.Y, 0);
            _rotateTransform = new RotateTransform3D(new AxisAngleRotation3D(new Vector3D(0, 0, 1), DetermineRotation(_creature)));
            _scaleTransform = new ScaleTransform3D(0.5, 0.5, 0.5);

            _scaleTransform.CenterX = _translateTransform.OffsetX;
            _scaleTransform.CenterY = _translateTransform.OffsetY;
            _scaleTransform.CenterZ = _translateTransform.OffsetZ;

            _rotateTransform.CenterX = _translateTransform.OffsetX;
            _rotateTransform.CenterY = _translateTransform.OffsetY;
            _rotateTransform.CenterZ = _translateTransform.OffsetZ;

            group.Children.Add(_translateTransform);
            group.Children.Add(_rotateTransform);
            group.Children.Add(_scaleTransform);

            this.ModelVisual3D.Transform = group;
            base.AddToScene();
        }

        public override void RemoveFromScene()
        {
            base.RemoveFromScene();
            _creature.GameObjectChanged -= CreatureChanged;
        }

        private void CreatureChanged(GameObject o)
        {
            _translateTransform.OffsetX = _creature.Location.X;
            _translateTransform.OffsetY = _creature.Location.Y;
            ((AxisAngleRotation3D)_rotateTransform.Rotation).Angle = DetermineRotation(_creature);

            _scaleTransform.CenterX = _translateTransform.OffsetX;
            _scaleTransform.CenterY = _translateTransform.OffsetY;
            _scaleTransform.CenterZ = _translateTransform.OffsetZ;

            _rotateTransform.CenterX = _translateTransform.OffsetX;
            _rotateTransform.CenterY = _translateTransform.OffsetY;
            _rotateTransform.CenterZ = _translateTransform.OffsetZ;
        }


        private int DetermineRotation(Creature c)
        {
            int z;
            switch (c.Orientation)
            {
                case Mud.Common.Physical.Orientation.North:
                    z = 0;
                    break;
                case Mud.Common.Physical.Orientation.NorthWest:
                    z = -45;
                    break;
                case Mud.Common.Physical.Orientation.West:
                    z = -90;
                    break;
                case Mud.Common.Physical.Orientation.SouthWest:
                    z = -135;
                    break;
                case Mud.Common.Physical.Orientation.South:
                    z = -180;
                    break;
                case Mud.Common.Physical.Orientation.SouthEast:
                    z = -180 -45;
                    break;
                case Mud.Common.Physical.Orientation.East:
                    z = -180 - 90;
                    break;
                case Mud.Common.Physical.Orientation.NorthEast:
                    z = -180 - 90 - 45;
                    break;
                default:
                    throw new ArgumentOutOfRangeException("c.Orientation");
            }
            z = z - 90;
            if(z<360) z+=360;
            return z;
        }

    }
}
